package Euler51;

import java.util.*;
import ReusableCode.*;

public class PrimeDigitReplacement {
	public static void main(String[] args) {
		int max = 999999;
		List<Integer> primes = PrimeFunctions.GetPrimes(max);
		HashSet<Integer> primesHash = PrimeFunctions.GetPrimesHash(max);
		List<List<boolean[]>> boolSets = new ArrayList<List<boolean[]>>();
		
		System.out.println("Working...");
		
		for(int i = 0; i <= MathFunctions.numberOfDigits(max); i++)
		{
			boolSets.add(generateBooleanSets(i));
		}
		
		for(Iterator<Integer> iter = primes.iterator(); iter.hasNext();)
		{
			int prime = iter.next();
			int numDigs = MathFunctions.numberOfDigits(prime);
			
			if(numDigs>1)
			{
				List<boolean[]> boolSet = boolSets.get(numDigs);
				
				for(Iterator<boolean[]> boolIter = boolSet.iterator(); boolIter.hasNext();)
				{
					boolean[] bools = boolIter.next();
					int numPrimes = getNumPrimes(bools, prime, primesHash);
					
					if(numPrimes==8)
					{
						System.out.println(prime + "  " + numPrimes);
						return;
					}
					//System.out.println(prime + "  " + numPrimes);
				}
			}
		}
		
		/*
		for(int k = 0; k < boolSets.size(); k++)
		{
			List<boolean[]> sets = boolSets.get(k);
			for(int i = 0; i < sets.size(); i++)
			{
				boolean set[] = sets.get(i);
				for(int j = 0; j < set.length; j++)
				{
					System.out.print(set[j] + " ");
				}
				System.out.println();
			}
			System.out.println();
			System.out.println();
		}*/
	}

	static int getNumPrimes(boolean[] replace, int num, HashSet<Integer> primesHash)
	{	
		int digits[] = MathFunctions.reverseArray(MathFunctions.getDigits(num));
		int counter = 0;
		
		//Make sure the given number matches the given boolean pattern, if not return 0;
		int dig = -1;
		for(int i = 0; i < digits.length; i++)
		{
			if(replace[i])
			{
				if(dig>=0)
				{
					if(!(dig == digits[i]))
					{
						return 0;
					}
				}
				else 
				{
					dig = digits[i];
				}
			}
		}
		
		for(int i = 0; i < 10; i++)
		{
			int number[] = digits.clone();
			
			for(int j = 0; j < digits.length; j++)
			{
				if(replace[j])
				{
					number[j] = i;
				}
			}
				
			int prime = MathFunctions.safeLongToInt(MathFunctions.arrayToLong(number));
			if(primesHash.contains(prime) && (MathFunctions.numberOfDigits(prime)==digits.length))
			{
				counter++;
			}
		
		}
		
		return counter;
	}
	
	static List<boolean[]> generateBooleanSets(int size)
	{
		List<boolean[]> sets = new ArrayList<boolean[]>();
		int max = (int) Math.pow(2, size);
		boolean arr[];
		
		for(int i = 1; i < max-1; i++)
		{
			arr = new boolean[size];
			
			for(int j = 0; j < size; j++)
			{
				if(((i >> j) & 1)==1)
				{
					arr[j]=true;
				}
			}
			
			sets.add(arr);
		}
		
		return sets;
	}
}
